package ewa.big.controller;

import ewa.big.gameapi.Field;
import ewa.big.gameapi.Game;
import ewa.big.gameapi.Player;
import ewa.big.utilities.Utility;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.xml.datatype.DatatypeConfigurationException;
import org.icefaces.application.PushRenderer;

/**
 * <b>Web Engineering - UE3</b>
 * <p>
 *
 * This class represents the maedn control of the "Mensch aergere Dich nicht" game.
 * 
 * @version 1.00 (01.05.2012)
 *  
 */
@ManagedBean(name = "mc")
@SessionScoped
public class MaednControl implements Serializable {
  public static final int MAX_PLAYERS = 2;
  private static final long serialVersionUID = 1L;
  private final static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(Game.class.getName());
  
  private String playername = "Supermario";
  private Player player;
  private Player computeropponent;
  private Game   game;
  private int    score = 0;
    
  private String imgPath = "img/";
  private String imgExt  = ".png";
  
  boolean uuidSet = false;
  boolean tweetSuccess = true;
  boolean highscorePublishSuccess = true;

  private String PUSH_GROUP;
  private List<Player> playerlist;
  /** 
   * C'tor - Creates a new instance of MaednControl 
   */
  public MaednControl() {
  } // end C'tor

  public MaednControl(int gameId){
      this.PUSH_GROUP = Integer.toString(gameId); 
      this.playerlist = new ArrayList<Player>();
  }
  /**
   * C'tor - Creates a new instance of MaednControl.
   *
   * @param playername    the name of the player.
   */
  public MaednControl(String playername) {
    this.playername = playername;
    init();
  } // end C'tor

  /**
   * Initializes a new game.
   */
  public void init() {
    //List<Player> playerlist = new ArrayList<Player>();
        
    player = new Player(playername);
    playerlist.add(player);
    computeropponent = new Player("Computer");
    playerlist.add(computeropponent);
    score = 0;
    this.game = new Game(playerlist, true);
    uuidSet = false;
    tweetSuccess = true;
    highscorePublishSuccess = true;
    
  } // end init
  
  /**
   * Restart the game.
   * 
   * @return the forward uri.
   */
  public String restartGame() {
    init();
    return "table";
  } // end restartGame

  /**
   * Get the name of the current player.
   *
   * @return the name of the current player.
   */
  public String getCurrentPlayerName() {
    return playername;
  } // end getCurrentPlayerName
  
  /**
   * Set the name of the current player.
   *
   * @param playername    the name of the player to set.
   */
  public void setCurrentPlayerName(String playername) {
    this.playername = playername;
  } // end setCurrentPlayerName

  /**
   * Returns the time already spent on this game
   * 
   * @return the time already spent on this game
   */
  public String getTime() {
    long milliseconds = game.getSpentTime();
    return String.format("%d min, %d sec",
           TimeUnit.MILLISECONDS.toMinutes(milliseconds),
          (TimeUnit.MILLISECONDS.toSeconds(milliseconds) - 
           TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milliseconds)))
    );
  } // end getTime
   
  /**
   * Specifies whether this game is over or not
   * 
   * @return <code>true</code> if this game is over, <code>false</code> 
   *         otherwise.
   */
  public boolean isGameOver() {
    return game.isGameOver();
  } // end isGameOve

  /**
   * Returns the rounds already played in this game
   * 
   * @return the rounds already played in this game
   */
  public int getRound() {
    return game.getRound();
  } // end getRound

  /**
   * Returns an unmodifiable list of the players participating in this game
   * 
   * @return an unmodifiable list of the players participating in this game
   */
  public List<Player> getPlayers() {
    return game.getPlayers();
  } // end getPlayers
    
  /**
   * Returns the name of the currently leading player.
   * 
   * @return the name of the currently leading player.
   */
  public String getLeaderName() {
    Player leader = game.getLeader();
    if(leader == null) {
      // mehrere fuehrende
      FacesContext ctx = FacesContext.getCurrentInstance();
      return Utility.getResourceText(ctx, "msg", "leader_more");
    } else {
      return leader.getName();
    }
  } // end getLeaderName
    
  /**
   * Specifies if a counter of a player occupies the field identified by 
   * <code>index</code> and when yes which player's counter occupies it
   * 
   * @param index Index of the field for which should be checked if and which
   *        player's counter occupies it
   * @return number of the player whose counter occupies the field identified
   *         by the given <code>intex</code>, i.e., 1, 2, 3 or 4; or -1
   *         if no counter occupies this field
   */
  public int isFieldOccupied(int index) {
    return this.game.getBoardFields().get(index - 1).getOccupyingPlayer();
  } // end isFieldOccupied

  /**
   * Rolls the dice for the player
   */
  public void rollDice() throws DatatypeConfigurationException {
    if(isGameOver())  return;
    this.score = game.rollthedice(player);
  } // end rollDice

  /**
   * Returns the score thrown by the player
   * 
   * @return the score thrown by the player
   */
  public int getScore(){
    return this.score;
  } // end getScore

  /**
   * Returns the score of the computer opponent
   * 
   * @return the score of the computer-controlled opponent
   */
  public String getOpponentScore(){
    StringBuilder sb = new StringBuilder("");
    List<Integer> opponentScore = game.getOpponentScore();
    if(opponentScore == null || opponentScore.isEmpty())  return "-";
    for(int i = 0; i < opponentScore.size(); i++) {
      sb.append(opponentScore.get(i));
      if(i < opponentScore.size() - 1)  sb.append("-");
    }
    return sb.toString();
  } // end getOpponentScore

  /**
   * Get the image path.
   *
   * @return the image path.
   */
  public String getImgPath() {
    return imgPath;
  } // end getImgPath

  /**
   * Set the image path.
   *
   * @param imagePath    the image path to set
   */
  public void setImgPath(String imgPath) {
    this.imgPath = imgPath;
  } // end setImgPath

  /**
   * Get the image extension.
   *
   * @return the imgExt.
   */
  public String getImgExt() {
    return imgExt;
  } // end getImgExt

  /**
   * Set the image extension.
   *
   * @param imgExt    the image extension to set
   */
  public void setImgExt(String imgExt) {
    this.imgExt = imgExt;
  } // end setImgExt

  /**
   * Returns the fields of the board
   *
   * @return fields of the board
   */
  public List<Field> getBoardFields() {
    return game.getBoardFields();
  } // end getBoardFields

  /**
   * Get the name of the graphics image for the field specified.
   * 
   * @param fieldnumber    the number of the field.
   * @param fieldcolor     the color of the field (-1 normally, 1 .. 4 for houses)
   * @return the image name
   */
  public String getFieldImage(int fieldnumber, int fieldcolor) {
    String image = "field";

    if(fieldcolor != -1) {
      image += fieldcolor;
    } else {
      //first field, set color
      if(fieldnumber == 1) {
        image += 1;
      }
      if(fieldnumber == 11) {
        image += 2;
      }
      if(fieldnumber == 21) {
        image += 3;
      }
      if(fieldnumber == 31) {
        image += 4;
      }
    }
    int locatedPlayer = isFieldOccupied(fieldnumber);
    if(locatedPlayer != -1)  image += "_player" + locatedPlayer;

    return getImgPath() + image + getImgExt();
  } // end getFieldImage

  /**
   * Get title / alternate text.
   *
   * @param fieldnumber       the number of the field.
   * @param fieldcolor        the color of the field (-1 normally, 1 .. 4 for houses).
   * @param startingsquare    "true" for starting square.
   * @param homebase          "true" for homebase.
   * @return the title / alternate text
   */
  public String getFieldText(int fieldnumber, int fieldcolor, boolean startingsquare, boolean homebase) {
    String title = "";

    FacesContext ctx = FacesContext.getCurrentInstance();
    String field       = Utility.getResourceText(ctx, "msg", "field");
    String firstField  = Utility.getResourceText(ctx, "msg", "first");
    String lastField   = Utility.getResourceText(ctx, "msg", "last");
    String startField  = Utility.getResourceText(ctx, "msg", "start");
    String finishField = Utility.getResourceText(ctx, "msg", "finish");

    if(fieldcolor == -1) {
      // first field, set title
      if(fieldnumber == 1) {
        title = ": " + firstField + " 1";
      }
      if(fieldnumber == 11) {
        title = ": " + firstField + " 2";
      }
      if(fieldnumber == 21) {
        title = ": " + firstField + " 3";
      }
      if(fieldnumber == 31) {
        title = ": " + firstField + " 4";
      }
      // last field, set title
      if(fieldnumber == 40) {
        title = ": " + lastField + " 1";
      }
      if(fieldnumber == 10) {
        title = ": " + lastField + " 2";
      }
      if(fieldnumber == 20) {
        title = ": " + lastField + " 3";
      }
      if(fieldnumber == 30) {
        title = ": " + lastField + " 4";
      }
    }
    if(startingsquare) {
      title = ": " + startField + " " + fieldcolor;
    }
    if(homebase) {
      title = ": " + finishField + " " + fieldcolor;
    }
    int locatedPlayer = isFieldOccupied(fieldnumber);
    if(locatedPlayer != -1)  title += ": " + Utility.getResourceText(ctx, "msg", "player") + " " + locatedPlayer;

    return field + " " + fieldnumber + title; 
  } // end getFieldText

  /**
   *
   *
   * @param fieldnumber
   * @param locatedPlayer
   * @param fieldcolor
   * @param startingsquare
   * @param homebase
   * @return 
   */
  public String getField(int fieldnumber, int locatedPlayer, int fieldcolor, boolean startingsquare, boolean homebase) {
    String title = "";
    String image = "field";

    if(fieldcolor != -1) {
      image += fieldcolor;
    } else {
      //first field, set color
      if(fieldnumber == 1) {
        image += 1;
      }
      if(fieldnumber == 11) {
        image += 2;
      }
      if(fieldnumber == 21) {
        image += 3;
      }
      if(fieldnumber == 31) {
        image += 4;
      }
      //last field, set title
      if(fieldnumber == 40) {
        title = ": letztes Feld Spieler 1";
      }
      if(fieldnumber == 10) {
        title = ": letztes Feld Spieler 2";
      }
      if(fieldnumber == 20) {
        title = ": letztes Feld Spieler 3";
      }
      if(fieldnumber == 30) {
        title = ": letztes Feld Spieler 4";
      }
      if(fieldnumber == 1) {
        title = ": erstes Feld Spieler 1";
      }
      if(fieldnumber == 11) {
        title = ": erstes Feld Spieler 2";
      }
      if(fieldnumber == 21) {
        title = ": erstes Feld Spieler 3";
      }
      if(fieldnumber == 31) {
        title = ": erstes Feld Spieler 4";
      }
    }
    if(startingsquare) {
      title = ": Startfeld Spieler " + fieldcolor;
    }
    if(homebase) {
      title = ": Zielfeld Spieler " + fieldcolor;
    }
    if(locatedPlayer != -1) {
      image += "_player" + locatedPlayer;
      title += ": Spieler " + locatedPlayer;
    }

    return "<img id='field" + fieldnumber + "' src='img/" + image + ".png' alt='Feld " + fieldnumber + title + "' title='Feld " + fieldnumber + title + "' />";
  } // end getField

  
    public String getTwitterString() {
        return game.getTwitterString();
    }
  
    public String getUuid(){
        return game.getUuid();
    }

    public boolean isUuidSet() {
        if(getTwitterString() != null){
            uuidSet = true;
        }
        return uuidSet;
    }

    public boolean isHighscorePublishSuccess() {
        return game.isHighscorePostSuccess();
    }

    public void setHighscorePublishSuccess(boolean highscorePublishSuccess) {
        this.highscorePublishSuccess = highscorePublishSuccess;
    }

    public boolean isTweetSuccess() {
        return game.isTweetSuccess();
    }

    public void setTweetSuccess(boolean tweetSuccess) {
        this.tweetSuccess = tweetSuccess;
    }
    
    public boolean addPlayer(Player p){
        if(playerlist.size()<MAX_PLAYERS){
            playerlist.add(p);
            
            PushRenderer.addCurrentSession(PUSH_GROUP);
            if(playerlist.size() == MAX_PLAYERS){
                init();
            }
            return playerlist.contains(p);
        }
        return false;
    }

    
    
} // end of class MaednControl
